<template>
  <div class="p-b-20px">
    <!-- top-label -->
    <div
      class="h-70px flex items-center justify-between p-x-32px b-b b-b-solid b-b-#e7e7e7 box-border"
    >
      <span class="c-#212121 text-16px font-600">发布视频</span>
      <div
        class="c-#61666d p-[12px_16px] cursor-pointer bg-#fff b b-solid b-#e7e7e7 font-600 text-14px hover:bg-#f4f4f4"
      >
        批量操作
      </div>
    </div>

    <!-- video-item -->
    <div class="p-x-32px">
      <!-- 合集label -->
      <div class="flex items-center m-y-20px gap-10px">
        <span class="text-14px">将以下所有视频</span>
        <div
          class="text-12px b b-solid b-#00a1d6 bg-#fff c-#00a1d6 p-[6px_11px] cursor-pointer"
        >
          加入合集
        </div>
      </div>

      <div class="bg-#f6f7f8 p-[20px_12px] b-rd-8px">
        <!-- 视频tab -->
        <div class="flex gap-10px">
          <div
            class="w-218px h-40px p-[10px_6px_10px_12px] m-b-10px b-rd-8px cursor-pointer"
            :class="selectVideoItemIndex === index ? 'bg-#00a1d6' : 'bg-#fff'"
            v-for="(item, index) in files"
            @click="selectVideoItemIndex = index"
          >
            <div
              class="flex items-center justify-between gap-24px"
              :class="selectVideoItemIndex === index ? 'c-#fff' : 'c-#18191c'"
            >
              <div
                class="text-14px overflow-hidden whitespace-nowrap text-ellipsis flex-1"
                :title="item.name.split('.').slice(0, -1).join('.')"
              >
                {{ item.name.split(".").slice(0, -1).join(".") }}
              </div>
              <span
                class="iconfont icon-guanbi text-14px cursor-pointer flex-shrink-0"
                @click.stop="deleteVideo(index)"
              ></span>
            </div>

            <div
              v-if="item.progressInfo.status === 0"
              class="text-10px p-t-8px flex items-center gap-4px"
              :class="
                selectVideoItemIndex === index ? 'c-#ffffffb3' : 'c-#9a9a9a'
              "
            >
              等待上传
            </div>

            <div
              v-if="item.progressInfo.status === 1"
              class="text-10px p-t-8px flex items-center gap-4px"
              :class="
                selectVideoItemIndex === index ? 'c-#ffffffb3' : 'c-#9a9a9a'
              "
            >
              上传中...
            </div>
            <div
              v-if="item.progressInfo.status === 2"
              class="text-10px p-t-8px flex items-center gap-4px"
              :class="
                selectVideoItemIndex === index ? 'c-#ffffffb3' : 'c-#43ce5b'
              "
            >
              <span class="iconfont icon-duihao2 text-12px"></span>
              <span>上传完成</span>
            </div>
          </div>

          <el-upload
            class="upload-demo w-98px h-60px text-12px c-#61666d bg-#fff text-center b-rd-8px flex items-center justify-center"
            :auto-upload="false"
            :on-change="handleChange(1)"
            :show-file-list="false"
            v-if="files.length < 5"
          >
            <span class="iconfont icon-jiahao"></span>
            <div>添加视频</div>
          </el-upload>
        </div>

        <!-- 视频上传进度 -->
        <div class="w-838px h-76px flex items-center">
          <span
            class="iconfont icon-file-video-fill c-#00a1d6 text-50px"
          ></span>

          <div class="flex-1">
            <p class="c-#222 text-13px">
              {{
                files[selectVideoItemIndex].name
                  .split(".")
                  .slice(0, -1)
                  .join(".")
              }}
            </p>

            <div
              v-if="files[selectVideoItemIndex].progressInfo.status === 1"
              class="flex items-center justify-between"
            >
              <div>
                <span class="c-#999 text-10px m-r-5px">
                  已经上传：{{
                    files[selectVideoItemIndex].progressInfo.uploadedMB
                  }}MB/ {{ files[selectVideoItemIndex].progressInfo.totalMB }}MB
                </span>
                <span class="c-#999 text-10px">
                  当前速度：
                  {{ files[selectVideoItemIndex].progressInfo.speedMBps }}MB/s
                  剩余时间：剩余时间：{{
                    files[selectVideoItemIndex].progressInfo.remainingSeconds
                  }}秒
                </span>
              </div>

              <div class="c-#999 text-12px">
                <span class=""
                  >{{
                    files[selectVideoItemIndex].progressInfo.percentage
                  }}%</span
                >
                <!-- <span
                  class="iconfont m-x-20px cursor-pointer"
                  :class="[
                    'iconfont',
                    isUploading ? 'icon-zanting' : 'icon-zantinganniu',
                  ]"
                ></span> -->
                <span
                  class="iconfont icon-zhongshi cursor-pointer m-l-10px"
                ></span>
              </div>
            </div>

            <div
              v-if="files[selectVideoItemIndex].progressInfo.status === 2"
              class="flex items-center justify-between"
            >
              <div
                class="text-10px p-t-8px flex items-center gap-4px c-#43ce5b"
              >
                <span class="iconfont icon-duihao2 text-12px"></span>
                <span>上传完成</span>
              </div>

              <el-upload
                :auto-upload="false"
                :on-change="handleChange(2)"
                :show-file-list="false"
                v-if="files.length < 5"
              >
                <div class="text-14px c-#00a1d6 cursor-pointer flex">
                  <span
                    class="iconfont icon-zhongshi m-x-10px text-19px v-mid"
                  ></span>
                  <span>更换视频</span>
                </div>
              </el-upload>
            </div>
            <el-progress
              class="m-t-10px"
              color="#43ce5b"
              :stroke-width="3"
              :percentage="files[selectVideoItemIndex].progressInfo.percentage"
              :show-text="false"
            />
          </div>
        </div>
      </div>
    </div>

    <!-- video info -->
    <div
      class="p-x-32px"
      v-if="
        files[selectVideoItemIndex].coverImgs[
          files[selectVideoItemIndex].selectImgIndex
        ]
      "
    >
      <p class="text-16px c-#222 font-600 m-y-20px">基本设置</p>
      <el-form
        ref="videoFormRef"
        :model="files[selectVideoItemIndex].videoFormData"
        :rules="rules"
        label-width="100px"
      >
        <el-form-item label="封面" prop="cover">
          <img
            class="w-169px h-127px cursor-pointer object-cover"
            :src="
              files[selectVideoItemIndex].dataImg ||
              files[selectVideoItemIndex].coverImgs[
                files[selectVideoItemIndex].selectImgIndex
              ].imgUrl
            "
            @click="handelCoverImgVisible = true"
          />
          <div class="flex flex-col h-127px flex-1 m-l-40px gap-10px">
            <div class="text-12px c-#757575 leading-24px">
              系统默认选中第一帧为视频封面，以下为更多智能推荐封面
            </div>
            <div class="flex gap-20px">
              <div
                v-for="(item, index) in files[selectVideoItemIndex].coverImgs"
                class="relative cursor-pointer"
                @click="
                  (files[selectVideoItemIndex].selectImgIndex = index),
                    (files[selectVideoItemIndex].dataImg = null)
                "
              >
                <img
                  class="w-120px h-90px cursor-pointer b-rd-4px object-cover"
                  :src="item.imgUrl"
                />
                <div
                  v-if="
                    !files[selectVideoItemIndex].dataImg &&
                    files[selectVideoItemIndex].selectImgIndex === index
                  "
                  class="absolute top-0 w-120px h-90px flex items-center justify-center bg-[rgba(0,0,0,.5)] b-2px b-solid b-#00a1d6 b-rd-4px"
                >
                  <span
                    class="iconfont icon-duihao c-#00a1d6 text-26px font-800"
                  ></span>
                </div>
              </div>
            </div>
          </div>
        </el-form-item>
        <el-form-item label="标题" prop="title">
          <el-input
            v-model="files[selectVideoItemIndex].videoFormData.title"
            placeholder="请输入稿件标题"
            maxlength="80"
            show-word-limit
          />
        </el-form-item>
        <el-form-item label="类型">
          <el-radio-group
            v-model="files[selectVideoItemIndex].videoFormData.videoType"
          >
            <el-radio
              v-for="dict in video_type"
              :key="dict.value"
              :value="parseInt(dict.value)"
              >{{ dict.label }}</el-radio
            >
          </el-radio-group>
        </el-form-item>

        <el-form-item
          v-if="files[selectVideoItemIndex].videoFormData.videoType === 1"
          label="转载来源"
        >
          <el-input
            v-model="files[selectVideoItemIndex].videoFormData.sourceInfo"
            placeholder="请输入转载来源"
          />
        </el-form-item>

        <el-form-item label="分区" prop="categoryId">
          <el-select
            v-model="files[selectVideoItemIndex].videoFormData.categoryId"
            placeholder="请选择视频分区"
            style="width: 240px"
          >
            <el-option
              v-for="item in contentCategoryList"
              :label="item.categoryName"
              :value="item.id"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="标签 - 待实现">
          <el-select placeholder="请选择视频标签" style="width: 240px">
            <el-option
              v-for="item in contentTagList"
              :label="item.tagName"
              :value="item.id"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="简介">
          <el-input
            v-model="files[selectVideoItemIndex].videoFormData.description"
            type="textarea"
            :rows="8"
            placeholder="填写更全面的相关信息，让更多的人能找到你的视频吧"
          />
        </el-form-item>

        <el-form-item label="加入合集">
          <el-select
            v-model="files[selectVideoItemIndex].videoFormData.collectionId"
            placeholder="请选择视频合集"
            style="width: 240px"
          >
            <template #header>
              <div
                class="text-center leading-24px text-14px c-#00a1d6 cursor-pointer"
                @click="collectionVisible = true"
              >
                <span
                  class="iconfont icon-jiahao text-18px v-btm font-800 m-x-10px"
                ></span>
                <span>添加合集</span>
              </div>
            </template>
            <el-option
              v-for="item in contentCollectionList"
              :label="item.title"
              :value="item.id"
            />
          </el-select>
        </el-form-item>

        <el-form-item label="二创设置">
          <el-checkbox
            v-model="files[selectVideoItemIndex].videoFormData.isRemix"
            false-value="0"
            true-value="1"
            >允许二创</el-checkbox
          >
        </el-form-item>

        <el-form-item label="可见范围" prop="visibility">
          <el-radio-group
            v-model="files[selectVideoItemIndex].videoFormData.visibility"
          >
            <el-radio
              v-for="dict in visibility"
              :key="dict.value"
              :value="parseInt(dict.value)"
              >{{ dict.label }}</el-radio
            >
          </el-radio-group>
        </el-form-item>

        <el-form-item label="互动设置">
          <el-checkbox
            v-model="files[selectVideoItemIndex].videoFormData.disableDanmaku"
            false-value="0"
            true-value="1"
            >关闭弹幕</el-checkbox
          >
          <el-checkbox
            v-model="files[selectVideoItemIndex].videoFormData.disableComment"
            false-value="0"
            true-value="1"
            >关闭评论</el-checkbox
          >
          <el-checkbox
            v-model="
              files[selectVideoItemIndex].videoFormData.enableFeaturedComments
            "
            false-value="0"
            true-value="1"
            >开启精选评论</el-checkbox
          >
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm()"> 立即投稿 </el-button>
        </el-form-item>
      </el-form>
    </div>

    <!-- 添加合集 -->
    <el-dialog
      v-model="collectionVisible"
      title="创建合集"
      width="30%"
      align-center
      :close-on-click-modal="false"
      @open="initCollectionFrom"
    >
      <el-input
        v-model="collectionFrom.title"
        placeholder="请输入标题，创建合集"
        maxlength="20"
        show-word-limit
        size="large"
      />
      <template #footer>
        <div class="text-center">
          <el-button
            class="bg-#00a1d6"
            type="primary"
            @click="saveContentCollection"
          >
            创建并加入
          </el-button>
          <el-button @click="collectionVisible = false">取消</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 处理视频封面 -->
    <el-dialog
      v-model="handelCoverImgVisible"
      @opened="initCoverImg"
      title="截取封面"
      width="760px"
      center
    >
      <div class="flex justify-between">
        <div class="w-530px h-298px">
          <cropper-canvas ref="cropperCanvas" background>
            <cropper-image
              ref="cropperImage"
              :src="
                files[selectVideoItemIndex].coverImgs[
                  files[selectVideoItemIndex].selectImgIndex
                ].imgUrl
              "
              alt="Picture"
              rotatable
              scalable
              skewable
              translatable
            />
            <cropper-handle action="move" plain />
            <cropper-selection
              id="cropperSelection"
              ref="cropperSelectionRef"
              initial-coverage="0.3"
              movable
              resizable
              outlined
            >
              <cropper-grid role="grid" covered />
              <cropper-crosshair centered />
              <cropper-handle
                action="move"
                theme-color="rgba(255, 255, 255, 0.35)"
              />
              <cropper-handle action="n-resize" />
              <cropper-handle action="e-resize" />
              <cropper-handle action="s-resize" />
              <cropper-handle action="w-resize" />
              <cropper-handle action="ne-resize" />
              <cropper-handle action="nw-resize" />
              <cropper-handle action="se-resize" />
              <cropper-handle action="sw-resize" />
            </cropper-selection>
          </cropper-canvas>
        </div>
        <div class="flex flex-col text-center gap-20px">
          <div>
            <p>4:3</p>
            <div class="w-[160px] h-[120px] b b-solid b-#999">
              <cropper-viewer
                selection="#cropperSelection"
                class="max-w-full max-h-full object-contain"
              />
            </div>
          </div>
          <div>
            <p>16:9</p>
            <div class="w-160px h-90px b b-solid b-#999">
              <cropper-viewer
                selection="#cropperSelection"
                class="max-w-full max-h-full object-contain"
              />
            </div>
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" @click="cutCoverImg()"> 确认 </el-button>
          <el-button @click="handelCoverImgVisible = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { getCurrentInstance, onMounted, reactive, ref, toRefs } from "vue";
import type { UploadFiles, UploadUserFile } from "element-plus";
import { uploadFile } from "@/api/file";
import type { AxiosProgressEvent } from "axios";
import type { VideoForm } from "@/api/video/types";
import { listContentCategory as listContentCategoryApi } from "@/api/contentCategory";
import type { ContentCategoryVO } from "@/api/contentCategory/types";
import { listContentTag as listContentTagApi } from "@/api/contentTag";
import type { ContentTagVO } from "@/api/contentTag/types";
import {
  listContentCollection as listContentCollectionApi,
  addContentCollection as addContentCollectionApi,
} from "@/api/contentCollection";
import type {
  ContentCollectionForm,
  ContentCollectionVO,
} from "@/api/contentCollection/types";
import { addVideo as addVideoApi } from "@/api/video";
import { delOss } from "@/api/oss";
import to from "await-to-js";
import "cropperjs";
import type { FormInstance } from "element-plus";
import { validateVideoForm } from "@/utils/validateVideoForm";
import router from "@/router";

const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { video_type, visibility } = toRefs<any>(
  proxy?.useDict("video_type", "video_status", "yes_no", "visibility")
);

// 接收父级文件参数
const props = defineProps<{
  files: UploadUserFile[];
}>();

const videoFormRef = ref<FormInstance>();
const contentCategoryList = ref<ContentCategoryVO[]>([]); // 内容分类列表
const contentTagList = ref<ContentTagVO[]>([]); // 内容标签列表
const contentCollectionList = ref<ContentCollectionVO[]>([]); // 内容合集列表
const collectionVisible = ref(false); // 是否显示添加合集
const handelCoverImgVisible = ref(false); // 是否显示处理视频封面
const cropperSelectionRef = ref(); // 裁剪框组件对象
const selectVideoItemIndex = ref(0); // 选中的视频索引

// 用于计算速度：记录上一次的时间和已上传字节数
let lastTime = 0;
let lastLoaded = 0;

// 立即投稿
const submitForm = async () => {
  const results = await Promise.all(
    files.value.map((file, index) =>
      validateVideoForm(file.videoFormData, rules, index)
    )
  );

  const allValid = results.every(Boolean);
  if (allValid) {
    const formList: VideoForm[] = [];
    for (let i = 0; i < files.value.length; i++) {
      const file = files.value[i];
      const f: File = file.dataImg
        ? dataURLtoFile(file.dataImg, `temp-${i}.png`)
        : file.coverImgs[file.selectImgIndex].file;

      let [err, res] = await to(uploadFile(f));
      if (err) {
        await delOss(
          files.value.flatMap((file) => [
            file.videoFormData.fileId,
            file.videoFormData.coverId,
          ])
        );
        return;
      }

      files.value[i].videoFormData.coverId = res.data.ossId;
      formList.push(files.value[i].videoFormData);
    }

    const [videoRrr, _] = await to(addVideoApi(formList));
    if (videoRrr) {
      await delOss(
        files.value.flatMap((file) => [
          file.videoFormData.fileId,
          file.videoFormData.coverId,
        ])
      );
      return;
    }

    // 强制刷新
    window.location.reload();

    ElMessage.success("提交成功 🎉");
  }
};

// 裁剪图片
async function cutCoverImg() {
  const res = await cropperSelectionRef.value.$toCanvas();
  const dataImage = res.toDataURL("image/png");
  files.value[selectVideoItemIndex.value].dataImg = dataImage;
  handelCoverImgVisible.value = false;
  // const file = dataURLtoFile(dataImage, "fileObj.value.name.png");
  // console.log("文件", file);
  // console.log("文件", file);
}

// 将data:image转成新的file
function dataURLtoFile(dataurl, filename) {
  var arr = dataurl.split(","),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  const blob = new Blob([u8arr], { type: mime });
  const file = new File([blob], filename, { type: mime });
  return file;
}

// 视频表单
const initFormData: VideoForm = {
  title: undefined,
  fileId: undefined,
  description: undefined,
  coverId: undefined,
  collectionId: undefined,
  categoryId: undefined,
  videoType: 0,
  sourceInfo: undefined,
  isRemix: undefined,
  visibility: 0,
  disableDanmaku: undefined,
  disableComment: undefined,
  enableFeaturedComments: undefined,
  size: 0,
  videoStatus: 1, //待审核
};

// 定义上传进度结构
type ProgressInfo = {
  uploadedMB: string; // 已上传（MB）
  totalMB: string; // 总大小（MB）
  speedMBps: string; // 上传速度（MB/s）
  remainingSeconds: string; // 预计剩余时间（秒）
  percentage: number; // 上传进度百分比
  status: number; // 上传状态 0-未开始 1-进行中 2-完成 3-失败
};

// 整体响应式表单
const files = ref(
  props.files.map((file) => ({
    ...file,
    progressInfo: {
      uploadedMB: "0",
      totalMB: (file.size / (1024 * 1024)).toFixed(2),
      speedMBps: "0",
      remainingSeconds: "0",
      percentage: 0,
      status: 0, // 上传状态 0-未开始 1-进行中 2-完成 3-失败
    } as ProgressInfo,
    videoFormData: { ...initFormData },
    coverImgs: [],
    selectImgIndex: 0,
    dataImg: null, // 裁剪的图片数据
  }))
);

// 校验规则
const rules = {
  cover: [
    {
      required: true,
      validator: () => true,
      trigger: "blur",
    },
  ],
  title: [{ required: true, message: "视频标题不能为空", trigger: "blur" }],
  categoryId: [
    {
      required: true,
      message: "请选择视频分区",
      trigger: "change",
    },
  ],
};

// 合集表单
const collectionFrom = ref<ContentCollectionForm>({
  contentType: 1,
});

// 合集列表
const collectionList = async () => {
  const contentCollectionRes = await listContentCollectionApi();
  contentCollectionList.value = contentCollectionRes.rows;
};

// 保存合集
const saveContentCollection = async () => {
  await addContentCollectionApi(collectionFrom.value);
  await collectionList();
  collectionVisible.value = false;
};

// 打开集合添加对话框时初始化表单
const initCollectionFrom = async () => {
  collectionFrom.value.title = "";
};

// 视频封面弹窗初始化
const initCoverImg = async () => {
  await cropperSelectionRef.value.$render();
  // await cropperSelectionRef.value.$center();
  // await cropperSelectionRef.value.$reset();
};

// 上传队列函数
const startUploadQueue = async () => {
  for (let i = 0; i < files.value.length; i++) {
    if (files.value[i].progressInfo.status === 2) {
      continue; // 如果已经上传完成，跳过
    }

    // 初始化
    lastTime = Date.now();
    lastLoaded = 0;
    const [err, res] = await to(
      uploadFile(files.value[i].raw, (progressEvent: AxiosProgressEvent) => {
        const now = Date.now();
        const timeDiff = (now - lastTime) / 1000;
        const loaded = progressEvent.loaded;
        const total = progressEvent.total || 1; // 防止除以 0
        const loadedDiff = loaded - lastLoaded;
        const speedMBps = (loadedDiff / timeDiff / (1024 * 1024)).toFixed(2);
        const uploadedMB = (loaded / (1024 * 1024)).toFixed(2);
        const totalMB = (total / (1024 * 1024)).toFixed(2);
        const remaining = total - loaded;
        const remainingSeconds = (
          remaining /
          (parseFloat(speedMBps) * 1024 * 1024)
        ).toFixed(1);
        const percentage = Number(((loaded / total) * 100).toFixed(0));

        files.value[i].progressInfo = {
          uploadedMB,
          totalMB,
          speedMBps,
          remainingSeconds,
          percentage,
          status: 1, // 上传状态 0-未开始 1-进行中 2-完成 3-失败
        };

        lastTime = now;
        lastLoaded = loaded;
      })
    );

    if (err) {
      console.error(`上传失败: ${files.value[i].name}`, err);
    } else {
      files.value[i].videoFormData.fileId = res.data.ossId;
      files.value[i].videoFormData.size = files.value[i].size;
    }

    files.value[i].progressInfo.status = 2; // 上传完成
  }

  console.log("全部上传完成");
};

// 获取视频随机封面
async function extractThreeFrames(file: File): Promise<Blob[]> {
  const url = URL.createObjectURL(file);
  const video = document.createElement("video");
  video.src = url;
  video.crossOrigin = "anonymous";

  // 等待视频加载完成
  await new Promise<void>((resolve) => {
    video.onloadedmetadata = () => resolve();
  });

  const duration = video.duration;

  // 避开首帧和尾帧一点点，避免黑屏或未解码
  const safeOffset = 0.5;
  const times = [
    Math.max(safeOffset, duration * 0.2),
    Math.max(safeOffset, duration * 0.5),
    Math.max(safeOffset, duration * 0.8),
  ].map((t) => Math.min(t, duration - safeOffset));

  const canvas = document.createElement("canvas");
  canvas.width = video.videoWidth;
  canvas.height = video.videoHeight;
  const ctx = canvas.getContext("2d");

  const blobs: Blob[] = [];

  for (const time of times) {
    await new Promise<void>((resolve, reject) => {
      video.currentTime = time;

      const onSeeked = () => {
        ctx?.drawImage(video, 0, 0, canvas.width, canvas.height);
        canvas.toBlob(
          (blob) => {
            if (blob) blobs.push(blob);
            resolve();
          },
          "image/jpeg",
          0.8
        );
        video.removeEventListener("seeked", onSeeked);
      };

      video.addEventListener("seeked", onSeeked);
      video.onerror = () => reject(new Error("视频 seek 出错"));
    });
  }

  URL.revokeObjectURL(url);
  return blobs;
}

onMounted(async () => {
  // 开始上传
  startUploadQueue();

  try {
    const [blobs, [catErr, catRes], [tagErr, tagRes], [collectionErr]] =
      await Promise.all([
        extractThreeFrames(files.value[0].raw), // 提取视频帧
        to(listContentCategoryApi()),
        to(listContentTagApi()),
        to(collectionList()),
      ]);

    // 视频帧处理
    if (blobs) {
      files.value[selectVideoItemIndex.value].coverImgs = blobs.map(
        (blob, index) => {
          const file = new File([blob], `frame_${index + 1}.jpg`, {
            type: blob.type,
          });
          return {
            file,
            imgUrl: URL.createObjectURL(file),
          };
        }
      );
    }

    // 分类处理
    if (catErr) {
      console.error("获取分类失败", catErr);
    } else {
      contentCategoryList.value = catRes.rows;
    }

    // 标签处理
    if (tagErr) {
      console.error("获取标签失败", tagErr);
    } else {
      contentTagList.value = tagRes.rows;
    }

    // 合集处理
    if (collectionErr) {
      console.error("获取合集失败", collectionErr);
    }
  } catch (err) {
    console.error("处理失败", err);
  }
});

// 删除视频函数
const deleteVideo = async (index: number) => {
  if (files.value.length === 1) {
    ElMessage.warning("至少保留一个视频");
    return;
  }

  const [err, _] = await to(
    delOss(files.value[selectVideoItemIndex.value].videoFormData.fileId)
  );

  if (err) {
    return;
  }

  // 删除当前视频项
  files.value.splice(index, 1);

  const total = files.value.length;

  // 如果删的是当前选中项
  if (selectVideoItemIndex.value === index) {
    // 如果删除的是最后一项，选中上一项（若有）
    if (index >= total) {
      selectVideoItemIndex.value = total - 1;
    } else {
      selectVideoItemIndex.value = index;
    }
  } else if (selectVideoItemIndex.value > index) {
    // 如果删的是前面的项，选中索引左移
    selectVideoItemIndex.value--;
  }
};

// 视频发生变化函数 // type 1-添加视频 2-更换视频
const handleChange = (type: number) => {
  return async (file: any, fileList: UploadFiles) => {
    console.log("文件变化", file, fileList);

    let data = {
      ...file,
      progressInfo: {
        uploadedMB: "0",
        totalMB: (file.size / (1024 * 1024)).toFixed(2),
        speedMBps: "0",
        remainingSeconds: "0",
        percentage: 0,
        status: 0,
      } satisfies ProgressInfo,
      videoFormData: { ...initFormData },
      coverImgs: [],
      selectImgIndex: 0,
      dataImg: null, // 裁剪的图片数据
    };

    if (type === 1) {
      files.value.push(data);
    } else {
      files.value.splice(selectVideoItemIndex.value, 1, data);
    }

    const blobs = await extractThreeFrames(file.raw);
    if (blobs) {
      files.value[
        type === 1 ? files.value.length - 1 : selectVideoItemIndex.value
      ].coverImgs = blobs.map((blob, index) => {
        const file = new File([blob], `frame_${index + 1}.jpg`, {
          type: blob.type,
        });
        return {
          file,
          imgUrl: URL.createObjectURL(file),
        };
      });
    }

    await startUploadQueue();
  };
};
</script>

<style lang="less" scoped>
::v-deep(.el-upload--text) {
  flex-direction: column;
}
cropper-canvas {
  height: 298px;
}
</style>
